﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OverStore.Runtime.Storage;
using OverStore.Runtime.Logger;
using System.Diagnostics;
using OverStore.Runtime.ObjectRepository;

namespace OverStore.Configuration.Builder.Fluent
{
    /// <summary>
    /// Contains set of nested classes helps to configure OverStore.
    /// </summary>
    public static class OverStoreConfigurationBuilder
    {
        /// <summary>
        /// Contains components are required for creating OverStore configuration.
        /// </summary>
        public class BuilderParameters
        {
            private readonly List<IComponentConfiguration<IRepositoryBase>> _Repositories = new List<IComponentConfiguration<IRepositoryBase>>();

            /// <summary>
            /// Gets or sets the data storage.
            /// </summary>
            /// <value>The data storage.</value>
            public IComponentConfiguration<IDataStorage> DataStorage { get; set; }

            /// <summary>
            /// Gets or sets the logger.
            /// </summary>
            /// <value>The logger.</value>
            public IComponentConfiguration<ILogger> Logger { get; set; }

            /// <summary>
            /// Gets the repositories.
            /// </summary>
            /// <value>The repositories.</value>
            public List<IComponentConfiguration<IRepositoryBase>> Repositories
            {
                get
                {
                    return _Repositories;
                }
            }

            /// <summary>
            /// Creates the configuration.
            /// </summary>
            public OverStoreConfiguration CreateConfiguration()
            {
                return new OverStoreConfiguration
                {
                    DataStorage = DataStorage,
                    Logger = Logger,
                    Repositories = Repositories,
                };
            }
        }

        /// <summary>
        /// Initializes OverStore configuration with the logger.
        /// </summary>
        public class LoggerStep
        {
            private readonly BuilderParameters _Params;

            /// <summary>
            /// Initializes a new instance of the <see cref="LoggerStep"/> class.
            /// </summary>
            /// <param name="parameters">The parameters.</param>
            public LoggerStep(BuilderParameters parameters)
            {
                Debug.Assert(parameters != null, "parameters != null");
                _Params = parameters;
            }

            /// <summary>
            /// Sets up the logger.
            /// </summary>
            public DataStorageStep WithLogger(IComponentConfiguration<ILogger> logger)
            {
                _Params.Logger = logger;
                return new DataStorageStep(_Params);
            }
        }

        /// <summary>
        /// Initializes OverStore configuration with the data storage.
        /// </summary>
        public class DataStorageStep
        {
            private readonly BuilderParameters _Params;

            /// <summary>
            /// Initializes a new instance of the <see cref="DataStorageStep"/> class.
            /// </summary>
            /// <param name="parameters">The parameters.</param>
            public DataStorageStep(BuilderParameters parameters)
            {
                Debug.Assert(parameters != null, "parameters != null");
                _Params = parameters;
            }

            /// <summary>
            /// Setups the data storage.
            /// </summary>
            public RepositoryStep WithDataStorage(IComponentConfiguration<IDataStorage> dataStorage)
            {
                if (Object.ReferenceEquals(dataStorage, null))
                    throw new ArgumentNullException("dataStorage");
                _Params.DataStorage = dataStorage;
                return new RepositoryStep(_Params);
            }
        }

        /// <summary>
        /// Initializes OverStore configuration with set of repositories.
        /// </summary>
        public class RepositoryStep
        {
            private readonly BuilderParameters _Params;

            /// <summary>
            /// Initializes a new instance of the <see cref="RepositoryStep"/> class.
            /// </summary>
            /// <param name="parameters">The parameters.</param>
            public RepositoryStep(BuilderParameters parameters)
            {
                Debug.Assert(parameters != null, "parameters != null");
                _Params = parameters;
            }

            /// <summary>
            /// Adds the repository to OverStore configuration.
            /// </summary>
            public RepositoryStep AddRepository(IComponentConfiguration<IRepositoryBase> repository)
            {
                if (Object.ReferenceEquals(repository, null))
                    throw new ArgumentNullException("repository");
                _Params.Repositories.Add(repository);
                return this;
            }

            /// <summary>
            /// Completes OverStore configuration.
            /// </summary>
            public OverStoreConfiguration End()
            {
                return _Params.CreateConfiguration();
            }
        }
    }

    /// <summary>
    /// Entry point for configure OverStore.
    /// </summary>
    public static class OverStoreFluent
    {
        /// <summary>
        /// Begins OverStore configuration.
        /// </summary>
        public static OverStoreConfigurationBuilder.LoggerStep Configure()
        {
            var p = new OverStoreConfigurationBuilder.BuilderParameters();
            return new OverStoreConfigurationBuilder.LoggerStep(p);
        }
    }

}
